package com.hollycrm.hollysqm.core.waveform.wordcloud;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;

public class WordsLine {

	public static class MapComparator implements Comparator<WordMapping> {
		public int compare(WordMapping o1, WordMapping o2) {
			return o2.value - o1.value;
		}
	}

	public static BufferedImage createWordsLine(String fileName,List<WordPlot> words, String fontName, Integer fontSize) throws IOException {
		if (words == null )
			return null;
		if (fontSize == null)
			fontSize = FONT_SIZE;
		fontName = validateFontName(fontName, DEF_FONT);
		BufferedImage bi = ImageIO.read(new FileInputStream(fileName));;
		if (bi == null)
			return null;
		if (paintWords(bi, words, fontName,fontSize) < 1)
			return null;
		else
			return bi;
	}

	public static BufferedImage createWordsLine(BufferedImage bi,List<WordPlot> words, String fontName, Integer fontSize) throws IOException {
		if (words == null )
			return null;
		if (fontSize == null)
			fontSize = FONT_SIZE;
		fontName = validateFontName(fontName, DEF_FONT);
		if (bi == null)
			return null;
		if (paintWords(bi, words, fontName,fontSize) < 1)
			return null;
		else
			return bi;
	}

	private static String validateFontName(String fontName, String defFont) {
		if (fontName != null) {
			Font font = new Font(fontName, 0, 16);
			if (font.getName().equals(fontName))
				return fontName;
		}
		return defFont;
	}

	private static BufferedImage createBufferedImage(int width, int height) {
		BufferedImage bi = new BufferedImage(
				width, height, 2);
		Graphics2D g2 = bi.createGraphics();
		bi = g2.getDeviceConfiguration()
				.createCompatibleImage(width, height, 3);
		g2.dispose();
		return bi;
	}

	private static int paintWords(BufferedImage bi, List<WordPlot> words,
			String fontName, int fontSize) {
		PlotMap plotMap = initBitMap(bi);
		Graphics2D g2 = bi.createGraphics();
		int wordCount = 0;
		int size = words.size();
		for (int i = 0; i < size; i++) {
			do {
				Font font = initFont(g2, fontName, fontSize);
				Rectangle2D bounds = getStringBounds(g2, font,
						words.get(i).getWord());
				Rectangle2D rect = bounds.getBounds();
				rect.setRect(words.get(i).getX(), words.get(i).getY(),  words.get(i).getW(),
						 words.get(i).getH());
				rect = findSpace(plotMap, rect);
				if (rect != null) {

						//direction = 0;
						paintOneWord(bi, g2, words.get(i), 0, rect,bounds);

					updateBitMap(plotMap, rect);
					wordCount++;
					break;
				}
			} while (true);
		}

		return wordCount;
	}

	private static PlotMap initBitMap(BufferedImage bi) {
		int w = (int) Math.ceil((double) bi.getWidth() );
		int h = (int) Math.ceil((double) bi.getHeight() );
		return new PlotMap(w, h);
	}

	private static Font initFont(Graphics2D g2, String fontName,
			Integer fontSize) {

		Font font = new Font(fontName, 1, fontSize);
		g2.setFont(font);
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		return font;
	}

	public static Rectangle2D getStringBounds(Graphics2D g2,
			Font font, String key) {
		java.awt.font.FontRenderContext frc = g2.getFontRenderContext();
		Rectangle2D rc = font.getStringBounds(key, frc);
		return rc;
	}

	private static Rectangle2D findSpace(PlotMap plotMap, Rectangle2D rect) {

		int x = (int)rect.getX();
		int y = (int)rect.getY();
		int w = (int)rect.getWidth();
		int h = (int)rect.getHeight();
		int k=0;
		int maxK=(y>100)?200:80;
		for( k=y;k<=maxK;k=k+h){
			if (isClean(plotMap, x, k, w, h)) {
				//	System.out.println(x+","+k+","+w+","+h);
					return new Rectangle(x, k, w, h);
				}
			if(k>=maxK-h){
				x=x+w;
				k=y;
			}
		}


		return null;

	}




	private static boolean isClean(PlotMap plotMap, int x, int y, int w, int h) {

		for (int i = x; i < x + w; i++)
			for (int j = y; j < y + h; j++)
				if (plotMap.isUsed(i, j))
					return false;

		return true;
	}

	public static void paintOneWord(BufferedImage bi, Graphics2D g2,
			WordPlot word, int direction, Rectangle2D rect, Rectangle2D orgBounds) {

		int x=(int) rect.getX();
		int y=(int) (rect.getY());
		if(word.isLight()){
			g2.setPaint(Color.BLACK);
		}else {
			if (y > 100)
				g2.setPaint(Color.RED);
			else
				g2.setPaint(Color.GREEN);
		}
		g2.drawString(word.getWord(), x, y);
		bi.flush();
	}

	private static Paint randomColor() {
		int rgb = COLORS[(int) (Math.random() * 10000D) % COLORS.length];
		return new Color(rgb);
	}

	private static void updateBitMap(PlotMap plotMap, Rectangle2D rect) {
		int x = (int)rect.getX();
		int y = (int)rect.getY();
		int w = (int)rect.getWidth();
		int h = (int)rect.getHeight();
		for (int i = x; i < x + w; i++)
			for (int j = y; j < y + h; j++)
				plotMap.setUsed(i, j);


	}

	public static BufferedImage mixImages(BufferedImage images[],
			Float alphas[], int width, int height) {
		return mixImages(images, alphas, createBufferedImage(width, height));
	}

	public static BufferedImage mixImages(BufferedImage images[],
			Float alphas[], BufferedImage targetImage) {
		if (images == null || images.length < 1)
			return targetImage;
		if (targetImage == null) {
			for (int i = 0; i < images.length; i++) {
				if (images[i] == null)
					continue;
				targetImage = createBufferedImage(images[0].getWidth(),
						images[0].getHeight());
				break;
			}

			if (targetImage == null)
				return null;
		}
		Graphics2D g2 = targetImage.createGraphics();
		float alpha = 1.0F;
		for (int i = 0; i < images.length; i++)
			if (images[i] != null) {
				if (alphas != null && i < alphas.length && alphas[i] != null)
					alpha = alphas[i].floatValue();
				else
					alpha = 1.0F;
				g2.setComposite(AlphaComposite.getInstance(3, alpha));
				g2.drawImage(images[i], 0, 0, targetImage.getWidth(),
						targetImage.getHeight(), 0, 0, images[i].getWidth(),
						images[i].getHeight(), null);
			}

		g2.dispose();
		targetImage.flush();
		return targetImage;
	}


	public static final int MIN_WIDTH = 320;
	public static final int MIN_HEIGHT = 240;
	public static final int MAX_WIDTH = 2560;
	public static final int MAX_HEIGHT = 1920;
	public static final int BLOCK = 4;
	public static final String DEF_FONT = "微软雅黑";
	public static final int FONT_SIZE = 12;
	private static final int COLORS[] = { 0x4169E1, 0x8B4513, 0xFA8072,
			0xF4A460, 0x2E8B57, 0xE374AB, 0xA0522D, 0x0874A1, 0x433B78,
			0x39536E, 0x066636, 0x4682B4, 0x806A4E, 0x474747, 0x008080,
			0x8F1F8F, 0xFC3E1C, 0x20B3A4, 0x3B8A94 };

}